#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <math.h>
#include <linux/input.h>
#include <time.h>
#include <stdlib.h>

#define BLACK 0x00000000  // 黑色
#define RED 0x00ff0000    // 红色
#define GREEN 0x0000ff00  // 绿色
#define YELLOW 0x00ffff00 // 黄色
#define BLUE 0x000000ff   // 蓝色
#define PURPLE 0x00ff00ff // 紫色
#define CYAN 0x0000ffff   // 青色
#define WHITE 0x00ffffff  // 白色
#define GRAY 0x00808080   // 灰色
#define PINK 0x00ff8080   // 粉色
#define ORANGE 0x00ff8000 // 橙色

#define UINT unsigned short
#define DWORD unsigned int
#define LONG unsigned int
#define WORD unsigned short

int color[] = {RED, GREEN, YELLOW, BLUE, PURPLE, CYAN, WHITE, GRAY, PINK, ORANGE};

// 14
struct tagBITMAPFILEHEADER
{
    WORD bfType;      // 位图文件的类型，必须为BM(1-2字节）
    DWORD bfSize;     // 位图文件的大小，以字节为单位（3-6字节）
    WORD bfReserved1; // 位图文件保留字，必须为0(7-8字节）
    WORD bfReserved2; // 位图文件保留字，必须为0(9-10字节）
    DWORD bfOffBits;  // 位图数据的起始位置，以相对于位图（11-14字节）
    // 文件头的偏移量表示，以字节为单位
} __attribute__((packed));

// 40
struct tagBITMAPINFOHEADER
{
    DWORD biSize;    // 本结构所占用字节数（15-18字节）
    LONG biWidth;    // 位图的宽度，以像素为单位（19-22字节）    ------图片的宽度
    LONG biHeight;   // 位图的高度，以像素为单位（23-26字节）   ------图片的高度
    WORD biPlanes;   // 目标设备的级别，必须为1(27-28字节）
    WORD biBitCount; // 每个像素所需的位数，必须是1（双色），（29-30字节）  ---位深
    // 4(16色），8(256色）或24（真彩色）之一
    DWORD biCompression; // 位图压缩类型，必须是 0（不压缩），（31-34字节）
    // 1(BI_RLE8压缩类型）或2(BI_RLE4压缩类型）之一
    DWORD biSizeImage;    // 位图的大小，以字节为单位（35-38字节）   ---图片颜色数据的大小
    LONG biXPelsPerMeter; // 位图水平分辨率，每米像素数（39-42字节）
    LONG biYPelsPerMeter; // 位图垂直分辨率，每米像素数（43-46字节)
    DWORD biClrUsed;      // 位图实际使用的颜色表中的颜色数（47-50字节）
    DWORD biClrImportant; // 位图显示过程中重要的颜色数（51-54字节）
} __attribute__((packed));

int main()
{
    srand(time(NULL));

    int fd_touch = open("/dev/input/event0", O_RDWR);
    if (fd_touch < 0)
    {
        printf("open touch error %s\n", strerror(errno));
        return -1;
    }
    printf("open touch success\n");

    // =====================
    int fd_lcd;
    fd_lcd = open("/dev/fb0", O_RDWR);

    if (fd_lcd < 0)
    {
        printf("open lcd error: %s\n", strerror(errno));
        return -1;
    }
    printf("open lcd success\n");

    int (*lcd_mmap)[800] = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd_lcd, 0);
    printf("mmap success\n");

    // =============================
    int fd_bmp = open("./test/Cat.bmp", O_RDONLY);
    int fd_bmp1 = open("./test/zoo.bmp", O_RDONLY);
    int fd_lyy = open("./test/lyy.bmp", O_RDONLY);
    if (fd_bmp < 0)
    {
        printf("open bmp error: %s\n", strerror(errno));
        return -1;
    }
    printf("open bmp success\n");

    // bmp头
    struct tagBITMAPFILEHEADER file_header;
    struct tagBITMAPINFOHEADER info_header;
    read(fd_bmp, &file_header, sizeof(file_header));
    read(fd_bmp, &info_header, sizeof(info_header));

    struct tagBITMAPFILEHEADER file_header1;
    struct tagBITMAPINFOHEADER info_header1;
    read(fd_bmp1, &file_header1, sizeof(file_header1));
    read(fd_bmp1, &info_header1, sizeof(info_header1));

    struct tagBITMAPFILEHEADER file_header2;
    struct tagBITMAPINFOHEADER info_header2;
    read(fd_lyy, &file_header2, sizeof(file_header2));
    read(fd_lyy, &info_header2, sizeof(info_header2));

    // bmp像素信息
    char buf_bmp[100][100 * 3] = {0};
    read(fd_bmp, buf_bmp, sizeof(buf_bmp));

    char buf_bmp1[100][100 * 3] = {0};
    read(fd_bmp1, buf_bmp1, sizeof(buf_bmp1));

    char buf_bmp2[480][800 * 3] = {0};
    read(fd_lyy, buf_bmp2, sizeof(buf_bmp2));

    // printf("file_header.bfType: %x\n", file_header.bfType);
    // printf("file_header.bfSize: %d\n", file_header.bfSize);

    // printf("info_header.biWidth: %d\n", info_header.biWidth);
    // printf("info_header.biHeight: %d\n", info_header.biHeight);

    // ================

    // for (int row = 0; row < 480; row++)
    // {
    //     for (int col = 0; col < 800; col++)
    //     {

    //         // lcd_mmap[99 - row][col] = buf_bmp[row][col * 3 + 0] << 0 | buf_bmp[row][col * 3 + 1] << 8 | buf_bmp[row][col * 3 + 2] << 16 | 0x00 << 24;
    //         int bmp_row = 479 - row; // BMP是倒序的
    //         int b = buf_bmp2[bmp_row][col * 3 + 0];
    //         int g = buf_bmp2[bmp_row][col * 3 + 1];
    //         int r = buf_bmp2[bmp_row][col * 3 + 2];
    //         lcd_mmap[row][col] = (0x00 << 24) | (r << 16) | (g << 8) | b;
    //     }
    // }

    for (int row = 0; row < 480; row++)
    {
        for (int col = 0; col < 800; col++)
        {
            if (row < 100 && col < 100)
            {
                // lcd_mmap[99 - row][col] = buf_bmp[row][col * 3 + 0] << 0 | buf_bmp[row][col * 3 + 1] << 8 | buf_bmp[row][col * 3 + 2] << 16 | 0x00 << 24;
                int bmp_row = 99 - row; // BMP是倒序的
                int b = buf_bmp[bmp_row][col * 3 + 0];
                int g = buf_bmp[bmp_row][col * 3 + 1];
                int r = buf_bmp[bmp_row][col * 3 + 2];
                lcd_mmap[row][col] = (0x00 << 24) | (r << 16) | (g << 8) | b;
            }
            else if (row > 379 && col > 699)
            {
                int bmp_row = 99 - (row - 380); // 转换为0-99，并反转
                int bmp_col = col - 700;        // 转换为0-99

                int b = buf_bmp1[bmp_row][bmp_col * 3 + 0];
                int g = buf_bmp1[bmp_row][bmp_col * 3 + 1];
                int r = buf_bmp1[bmp_row][bmp_col * 3 + 2];
                lcd_mmap[row][col] = (0x00 << 24) | (r << 16) | (g << 8) | b;
            }
            else
            {
                lcd_mmap[row][col] = 0x00;
            }
        }
    }

    // 读取触摸屏数据
    struct input_event buf;
    int x = -1, y = -1;
    int prev_x = -1, prev_y = -1; // 记录上一次的坐标
    int radius = 20;              // 圆的半径
    int color_index = 0;          // 随机颜色
    int count = 0;                // 计数器

    while (1)
    {
        if (count == 5)
        {
            color_index = (rand() + 1) % 10; // 随机颜色
            count = 0;
        }
        memset(&buf, 0, sizeof(buf));
        read(fd_touch, &buf, sizeof(buf));
        if (buf.type == EV_ABS)
        {
            if (buf.code == ABS_X)
            {
                x = buf.value * 800 / 1024;
            }
            else if (buf.code == ABS_Y)
            {
                y = buf.value * 480 / 600;
            }
        }
        if (buf.type == EV_SYN && x != -1 && y != -1)
        {

            // 绘制小圆边界     略微扩大边界，防止圆角部分无法删除干净
            int min_col = (prev_x > radius) ? prev_x - radius - 1 : 0;
            int max_col = (prev_x < 800 - radius) ? prev_x + radius + 1 : 800;
            int min_row = (prev_y > radius) ? prev_y - radius - 1 : 0;
            int max_row = (prev_y < 480 - radius) ? prev_y + radius + 1 : 480;

            printf("x = %d, y = %d\n", x, y);
            for (int row = min_row; row < max_row; row++)
            {
                for (int col = min_col; col < max_col; col++)
                {
                    int yx = col - prev_x;
                    int yy = row - prev_y;
                    if (pow(yx, 2) + pow(yy, 2) <= 20 * 20)
                    {
                        lcd_mmap[row][col] = 0x00000000;
                    }
                }
            }
            for (int row = min_row; row < max_row; row++)
            {
                for (int col = min_col; col < max_col; col++)
                {
                    int yx = col - x;
                    int yy = row - y;
                    if (pow(yx, 2) + pow(yy, 2) <= 20 * 20)
                    {
                        lcd_mmap[row][col] = color[color_index];
                    }
                }
            }
            prev_x = x;
            prev_y = y;
        }
        // 黑色屏幕底板开发板的 显示LCD分辨率 800*480 触摸屏的分辨率1024*600
        // 蓝色屏幕底板开发板的 显示LCD分辨率 800*480 触摸屏的分辨率800*480
        count++;
    }

    // 关闭文件
    munmap(lcd_mmap, 800 * 480 * 4);
    close(fd_lcd);
    close(fd_bmp);
    close(fd_bmp1);
    return 0;
}